package com.startest.sms.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.startest.sms.config.PhoneToken;
import com.startest.sms.dao.UserMapper;
import com.startest.sms.entity.dto.Response;
import com.startest.sms.pojo.Permission;
import com.startest.sms.pojo.Role;
import com.startest.sms.pojo.User;
import com.startest.sms.utils.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import java.math.BigInteger;
import java.security.interfaces.RSAPrivateKey;
import java.util.*;

@Service
public class UserServiceImpl implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    //根据角色查找对应权限
    @Override
    public List<Permission> getPermsByRole(Role role) {
        List<Permission> permissions = userMapper.selectPermsByRole(role);
        return permissions;
    }

    //根据用户查找对应角色
    @Override
    public List<Role> getRolesByUser(User user) {
        List<Role> roles = userMapper.selectRolesByUser(user);
        return roles;
    }

    //分配角色
    @Transactional
    @Override
    public Response<String> editUserRole(Integer userId, Integer[] roleIds) {
        try {
            userMapper.deleteUserRoleByUserId(userId);
            Map<String,Integer> map = new HashMap<>();
            map.put("userId",userId);
            for (Integer roleId : roleIds){
                map.put("roleId",roleId);
                userMapper.addUserRole(map);
            }
            return Response.ok("操作成功");
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.fail("操作失败");
        }

    }

    //获取角色并包装
    @Override
    public List<Map<String, Object>> getRoleTree() {
        //id text
        List<Role> roles = userMapper.selectRoleList();
        ArrayList<Map<String, Object>> list = new ArrayList<>();

        for (Role role: roles){
            HashMap<String, Object> map = new HashMap<>();
            map.put("id",role.getId());
            map.put("text",role.getRoleName());
            list.add(map);
        }
        return list;
    }

    //用户拥有的角色list
    @Override
    public Response<List<Integer>> getRoleIdsByUserId(Integer userId) {
        try {
            List<Integer> list = userMapper.selectRoleIdsByUserId(userId);
            return Response.ok(list);
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("操作失败");
        }
    }

    //删除用户
    @Transactional
    @Override
    public Response<String> deleteUser(Integer userId) {
        //1 级联删除用户角色表中信息  2 删除用户
        try {
            userMapper.deleteUserRoleByUserId(userId);
            userMapper.deleteUser(userId);
            return Response.ok("操作成功");
        }catch (Exception e){
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.fail("操作失败");
        }
    }

    //添加修改用户
    @Override
    public Response<String> editUser(User user) {
        try {
            if(user.getId()==null){
                //添加 密码加密处理 存储盐值
                userMapper.addUser(user);
            }else{
                //修改
                userMapper.updateUser(user);
            }
            return Response.ok("操作成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("操作失败");
        }
    }

    //查询userList
    @Override
    public List<User> getUserList() {
        return userMapper.selectUserList();
    }

    //删除权限
    @Transactional
    @Override
    public Response<String> deletePerm(Integer permId) {
        //2删除权限  1级联删除角色权限表中数据
        try {
            //1
            userMapper.deletePermRole(permId);
            //2
            userMapper.deletePerm(permId);
            return Response.ok("操作成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("操作失败");
        }
    }

    //添加、修改权限
    @Override
    public Response<String> editPerm(Permission perm) {
        try {
            if(perm.getId()==null){
                //添加
                userMapper.addPerm(perm);
            }else{
                //修改
                userMapper.updatePerm(perm);
            }
            return Response.ok("操作成功");
        }catch (Exception e){
            e.printStackTrace();
            return Response.fail("操作失败");
        }
    }

    //获取权限list
    @Override
    public List<Permission> getPermsList() {
        return userMapper.selectPermList();
    }

    //删除角色
    @Transactional()
    @Override
    public void deleteRole(Integer roleId) {
        //3.删除角色   1.级联删除角色权限表中角色信息  2.用户角色信息表中角色信息
        try {
            //1  可以做判断查询是否有对应roleId 再删除
            userMapper.deletePermRoleByRoleId(roleId);
            //2 可以做判断查询是否有对应roleId 再删除
            userMapper.deleteUserRoleByRoleId(roleId);
            //3
            userMapper.deleteRole(roleId);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    //查询角色拥有的权限
    @Override
    public List<Integer> selectPermsByRoleId(Integer roleId) {
        return userMapper.selectPermsByRoleId(roleId);
    }

    //编辑角色的权限
    @Override
    public void editRolePerm(Integer roleId, Integer[] permIds) {
        userMapper.deleteRolePerm(roleId);
        Map<String,Integer> map = new HashMap<>();
        map.put("roleId",roleId);
        for (Integer permId : permIds){
            map.put("permId",permId);
            userMapper.addRolePerm(map);
        }
    }

    //获取权限树
    @Override
    public List<Permission> selectPermList() {
        List<Permission> permList = userMapper.selectPermList();
        HashMap<Integer, Permission> map = new HashMap<>();
        List<Permission> parentList = new ArrayList<>();
        for (Permission perm : permList){
            map.put(perm.getId(),perm);
        }
        for (Permission perm : permList){
            if(perm.getParentId()==null || perm.getParentId()==0){
                parentList.add(perm);
            }else{
                Permission  parent= map.get(perm.getParentId());
                parent.getChildren().add(perm);
            }
        }
        return parentList;
    }

    //增加、修改角色
    @Override
    public Response<String> editRole(Role role) {
        if(role.getId()==null){
            //添加
            try {
                userMapper.addRole(role);
                return Response.ok("添加角色成功");
            } catch (Exception e) {
                e.printStackTrace();
                return Response.fail("添加失败");
            }

        }else{
            //修改
            try {
                userMapper.updateRole(role);
                return Response.ok("修改成功");
            } catch (Exception e) {
                e.printStackTrace();
                return Response.fail("修改失败");
            }
        }
    }

    //获取角色
    @Override
    public List<Role> selectRoleList() {
        return userMapper.selectRoleList();
    }

    /**
     * 用户名密码注册用户
     * @param username
     * @param pwd   @return  */
    @Override
    public Response<String> addUser(HttpServletRequest request, HttpServletResponse response, String username, String pwd) throws Exception {
        //查找用户名是否存在
        int count = userMapper.countUserName(username);
        if(count>0){
            return Response.fail("用户名已存在");
        }
        RSAPrivateKey privateKey = (RSAPrivateKey) request.getSession().getAttribute("privkey");
        byte[] bytes = new BigInteger(pwd, 16).toByteArray();
        byte[] decrypt = RSAUtil.decrypt(privateKey, bytes);
        String midd = new String(decrypt);
        String passworld = new StringBuffer(midd).reverse().toString();
        String salt = MD5Util.getSalt();
        String encryptPassword = MD5Util.encryptPassword(passworld, salt);
        User user = new User();
        user.setUserName(username);
        user.setUserPwd(encryptPassword);
        user.setSalt(salt);
        try {
            userMapper.addUser(user);
            return Response.ok("注册成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("注册失败");
        }
    }

    /**
     * 用户名密码登陆
     *
     * @param autoLogin
     * @param username
     * @param pwd
     * @return
     */
    @Override
    public Response<String> login(HttpServletRequest request, HttpServletResponse response, String username, String pwd, String autoLogin) throws Exception {
        //查找用户名是否存在
       /* int count = userMapper.countUserName(username);
        if(count<1){
            return Response.fail("用户名或密码错误");
        }*/
        RSAPrivateKey privateKey = (RSAPrivateKey) request.getSession().getAttribute("privkey");
        byte[] bytes = new BigInteger(pwd, 16).toByteArray();
        byte[] decrypt = RSAUtil.decrypt(privateKey, bytes);
        String midd = new String(decrypt);
        String passworld = new StringBuffer(midd).reverse().toString();
        String salt = userMapper.getSalt(username);
        String encryptPassword = MD5Util.encryptPassword(passworld, salt);
        //autoLogin!=null 自动登录，此处需要做一些额外的业务处理。。。。
        //例如往cookie中放一些东西，并设置保存时间


        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken shiroToken = new UsernamePasswordToken(username, encryptPassword);
        try {
            subject.login(shiroToken);
            org.apache.shiro.session.Session session = subject.getSession();
            User user = userMapper.selectUserByName(username);
            session.setAttribute(Constants.USER_ID,user.getUserName());
            return Response.ok("登录成功");
        }catch (DisabledAccountException e){
            logger.warn("账户未激活",e);
            return Response.fail("账户未激活");
        }catch (IncorrectCredentialsException | UnknownAccountException e){
            logger.warn("账户或密码错误",e);
            return Response.fail("账户或密码错误");
        }catch (ExcessiveAttemptsException e){
            logger.warn("登录次数超过5次，限制登录5分钟",e);
            return Response.fail("登录次数超过5次，限制登录5分钟");
        }catch (Exception e) {
            logger.warn("账户或密码错误",e);
            return Response.fail("登录失败");
        }
        /* int num = userMapper.selectUser(username,encryptPassword);
        if(num>0){
            //cookie中放入token，级别：会话，
            long currentTime = System.currentTimeMillis();
            long expiresTime = currentTime + 1000*60*60*24*7;
            String token = MD5Util.hash(username + System.currentTimeMillis());
            Cookie cookieToken = new Cookie("UTOKEN", token);
            cookieToken.setPath("/");
            if(autoLogin!=null){
                //如果勾选自动登录，则cookie中token时长为一周
                cookieToken.setMaxAge(60*60*24*7);
                //数据库中保存token与过期时间
                Date endtime = new Date(expiresTime);
                userMapper.insertToken(username,token,endtime);
            }
            response.addCookie(cookieToken);
            request.getSession().setAttribute("user",username);
            return Response.ok("登录成功");
        }else{
            return Response.fail("用户名或密码错误");
        }*/
    }

    //废除
    //自动登录
    @Override
    public Response<String> autoLogin(HttpServletRequest request, String token, Date datetime){
        User user = userMapper.selectUserByToken(token,datetime);
        if(user!=null){
            request.getSession().setAttribute("user",user.getUserName());
            return Response.ok("自动登录成功");
        }else {
            return Response.fail("自动登录失败");
        }
    }

    /**
     * 发送手机验证码
     * @param phone
     * @param request
     * @return
     */
    @Override
    public Response<String> sendSMS(String phone,HttpServletRequest request) {
        String RegionID = "cn-hangzhou";
        String AccessKeyID = "LTAIUKbEzrEr2C9E";
        String AccessKeySecret = "YU7dZ5PXmzb0HGD71r9sx7vHMefOPv";
        DefaultProfile profile = DefaultProfile.getProfile(RegionID, AccessKeyID, AccessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);
        CommonRequest req = new CommonRequest();
        req.setMethod(MethodType.POST);
        req.setDomain("dysmsapi.aliyuncs.com");
        req.setVersion("2017-05-25");
        req.setAction("SendSms");
        req.putQueryParameter("PhoneNumbers", phone);
        req.putQueryParameter("SignName", "星天海洋");
        req.putQueryParameter("TemplateCode", "SMS_160856381");
        String code = PhoneRandomCode.randomCode();
        req.putQueryParameter("TemplateParam", "{\"code\":"+code+"}");
        try {
            CommonResponse response = client.getCommonResponse(req);
            String data = response.getData();
            JSONObject jsonObject = JSON.parseObject(data);
            String value = jsonObject.getString("Code");
            String message = jsonObject.getString("Message");
            if("OK".equals(value)){
                //发送成功
                HashMap<String, Object> hashMap = new HashMap<>();
                HashMap<String,HashMap<String,Object>> map = new HashMap<>();
                hashMap.put("phone",phone);
                hashMap.put("code",code);
                hashMap.put("time",System.currentTimeMillis());
                map.put(phone,hashMap);
                HttpSession session = request.getSession();
                session.setMaxInactiveInterval(60*2);
                session.setAttribute(phone,map);
                return Response.ok("发送成功");
            }else{
                return Response.fail("错误信息"+ message);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("短信发送业务出现异常");
        }
    }

    /**
     * 手机号登录
     * @param phone
     * @param code
     * @param request
     * @return
     */
    @Override
    public Response<String> phoneLogin(String phone, String code,HttpServletRequest request) {
        Object attribute = request.getSession().getAttribute(phone);
        if(attribute==null){
            return Response.fail("验证码已过期");
        }
        Map<String, HashMap<String,Object>> map =  (Map<String, HashMap<String,Object>>)attribute;
        // System.out.println(map.get(phone).get("time"));
        if((System.currentTimeMillis()-(long)map.get(phone).get("time"))>1000*60*2){
            return Response.fail("验证码已过期");
        }
        if(!code.equals(map.get(phone).get("code"))){
            return Response.fail("验证码错误");
        }
        PhoneToken phoneToken = new PhoneToken(phone);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(phoneToken);
            Session session = subject.getSession();
            User user = userMapper.selectUserByPhone(phone);
            session.setAttribute(Constants.USER_ID,user);
            return Response.ok("登录成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Response.fail("登录失败");
        }
    }

    /**
     * 手机注册
     * @param phone
     * @param code
     * @param request
     * @return
     */
    @Override
    public Response<String> phoneReg(String phone, String code, HttpServletRequest request) {
        //判断手机是否已经注册
        int count = userMapper.selectByPhone(phone);
        if(count>0){
            return Response.fail("手机号已经注册");
        }
        Object attribute = request.getSession().getAttribute(phone);
        if(attribute==null){
            return Response.fail("验证码已过期");
        }
        Map<String, HashMap<String,Object>> map =  (Map<String, HashMap<String,Object>>)attribute;
        if((System.currentTimeMillis()-(long)map.get(phone).get("time"))>1000*60*2){
            return Response.fail("验证码已过期");
        }
        if(!code.equals(map.get(phone).get("code"))){
            return Response.fail("验证码错误,注册失败");
        }
        //填写注册信息 随机生成一个用户名
        String username = "MX_"+UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10);
        int num = userMapper.insertByPhone(username,phone);
        if(num==1){
            return Response.ok("注册成功");
        }else {
            return Response.fail("注册失败");
        }
    }

    /**
     * 邮箱注册
     * @param username
     * @param pwd
     * @param email
     * @param request
     * @return
     */
    @Override
    public Response<String> emailReg(String username, String pwd, String email, HttpServletRequest request) throws Exception{
        //查找用户名是否存在
        int count = userMapper.countUserName(username);
        if(count>0){
            return Response.fail("用户名已存在");
        }
        //密码解密
        RSAPrivateKey privateKey = (RSAPrivateKey) request.getSession().getAttribute("privkey");
        byte[] bytes = new BigInteger(pwd, 16).toByteArray();
        byte[] decrypt = RSAUtil.decrypt(privateKey, bytes);
        String midd = new String(decrypt);
        String passworld = new StringBuffer(midd).reverse().toString();
        //密码加密存储
        String salt = MD5Util.getSalt();
        String encryptPassword = MD5Util.encryptPassword(passworld, salt);
        //生成激活码
        String emailCode = UUID.randomUUID().toString().replaceAll("-","");
        //状态吗设置为0
        int state = 0;
        int num = userMapper.insertByEmail(username,encryptPassword,salt,email,emailCode,state);
        if(num>0){
            //开辟一个线程去执行发送邮件任务
            new Thread(new MailUtil(email,emailCode)).start();
            return Response.ok();
        }else{
            return Response.fail("由于不可抗力因素，失败");
        }
    }

    /**
     * 邮箱激活
     * @param code
     * @return
     */
    @Override
    public Response<String> emailCheck(String code) {
        int ID = userMapper.selectByEmailCode(code);
        if(ID>0){
            userMapper.updateEmailCode(ID);
            return Response.ok("恭喜您激活成功，请登录");
        }else{
            return Response.fail("您的激活码有误，请重新激活");
        }
    }

    @Override
    public User selectUserByPhone(String phone) {
        return userMapper.selectUserByPhone(phone);
    }

    @Override
    public User selectUserByName(String username) {
        return userMapper.selectUserByName(username);
    }




}
